using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace demo.Tool
{
    /// <summary>
    /// 日志级别枚举
    /// </summary>
    public enum LogLevel
    {
        Debug = 0,
        Info = 1,
        Warning = 2,
        Error = 3,
        Fatal = 4
    }

    public class operateLog
    {
        static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
        private static LogLevel _currentLogLevel = LogLevel.Info;
        private static readonly object _levelLock = new object();
        
        /// <summary>
        /// 设置或获取当前日志级别
        /// </summary>
        public static LogLevel CurrentLogLevel
        {
            get
            {
                lock (_levelLock)
                {
                    return _currentLogLevel;
                }
            }
            set
            {
                lock (_levelLock)
                {
                    _currentLogLevel = value;
                }
            }
        }
        public static void WriteLog(string logName, string logString)
        {
            LogWriteLock.EnterWriteLock();

            try
            {
                string GetDirectoryName = ConfigurationManager.AppSettings["logPath"].ToString() + "\\" + System.DateTime.Now.ToString("yyyyMMdd");

                if (Directory.Exists(GetDirectoryName) == false)
                {
                    Directory.CreateDirectory(GetDirectoryName);
                }
                string fileName = GetDirectoryName + "\\" + (System.DateTime.Now.ToString("yyyy-MM-dd") + logName + ".txt");

                StreamWriter dout = new StreamWriter(fileName, true);
                dout.Write("[" + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]>>" + logString + "\r\n");
                dout.Close();
            }
            catch (Exception)
            {
            }
            finally
            {
                //退出写入模式，释放资源占用
                //注意释放与进入次数相同否则会触发异常
                LogWriteLock.ExitWriteLock();
            }
        }

        public static void WriteLogHH(string logName, string logString)
        {
            LogWriteLock.EnterWriteLock();

            try
            {
                string GetDirectoryName = ConfigurationManager.AppSettings["logPath"].ToString() + "\\" + System.DateTime.Now.ToString("yyyyMMdd");

                if (Directory.Exists(GetDirectoryName) == false)
                {
                    Directory.CreateDirectory(GetDirectoryName);
                }
                string fileName = GetDirectoryName + "\\" + (System.DateTime.Now.ToString("yyyy-MM-dd HH") + logName + ".txt");

                StreamWriter dout = new StreamWriter(fileName, true);
                dout.Write("[" + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]>>" + logString + "\r\n");
                dout.Close();
            }
            catch (Exception)
            {
            }
            finally
            {
                //退出写入模式，释放资源占用
                //注意释放与进入次数相同否则会触发异常
                LogWriteLock.ExitWriteLock();
            }
        }

        /// <summary>
        /// 生成日志
        /// </summary>
        /// <param name="readme"></param>
        public static void WriteLog(string readme)
        {
            WriteLog(readme, LogLevel.Info);
        }
        
        /// <summary>
        /// 写入指定级别的日志
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="level">日志级别</param>
        public static void WriteLog(string message, LogLevel level)
        {
            // 检查日志级别是否需要记录
            if (level < CurrentLogLevel)
            {
                return;
            }
            
            LogWriteLock.EnterWriteLock();
            try
            {
                string logPath = GetLogPath();
                string GetDirectoryName = logPath + "\\" + System.DateTime.Now.ToString("yyyyMMdd");

                if (Directory.Exists(GetDirectoryName) == false)
                {
                    Directory.CreateDirectory(GetDirectoryName);
                }
                
                string fileName = GetDirectoryName + "\\log" + (System.DateTime.Now.ToString("yyyy-MM-dd") + ".txt");
                string levelStr = GetLevelString(level);
                string threadInfo = $"[线程:{Thread.CurrentThread.ManagedThreadId}]";
                string processInfo = $"[进程:{Process.GetCurrentProcess().Id}]";
                
                using (StreamWriter writer = new StreamWriter(fileName, true, Encoding.UTF8))
                {
                    writer.WriteLine($"\r\n操作时间：{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
                    writer.WriteLine($"日志级别：{levelStr}");
                    writer.WriteLine($"线程信息：{threadInfo}");
                    writer.WriteLine($"进程信息：{processInfo}");
                    writer.WriteLine($"操作事件：{message}");
                    writer.WriteLine("".PadRight(80, '-'));
                }
            }
            catch (Exception ex)
            {
                // 如果日志写入失败，尝试写入到事件日志
                try
                {
                    string eventSource = "DemoApplication";
                    if (!EventLog.SourceExists(eventSource))
                    {
                        EventLog.CreateEventSource(eventSource, "Application");
                    }
                    EventLog.WriteEntry(eventSource, $"日志写入失败：{ex.Message}\n原始消息：{message}", EventLogEntryType.Error);
                }
                catch
                {
                    // 如果连事件日志都写入失败，则忽略（避免无限循环）
                }
            }
            finally
            {
                //退出写入模式，释放资源占用
                //注意释放与进入次数相同否则会触发异常
                LogWriteLock.ExitWriteLock();
            }
        }
        
        /// <summary>
        /// 写入调试日志
        /// </summary>
        /// <param name="message">日志消息</param>
        public static void WriteDebug(string message)
        {
            WriteLog(message, LogLevel.Debug);
        }
        
        /// <summary>
        /// 写入信息日志
        /// </summary>
        /// <param name="message">日志消息</param>
        public static void WriteInfo(string message)
        {
            WriteLog(message, LogLevel.Info);
        }
        
        /// <summary>
        /// 写入警告日志
        /// </summary>
        /// <param name="message">日志消息</param>
        public static void WriteWarning(string message)
        {
            WriteLog(message, LogLevel.Warning);
        }
        
        /// <summary>
        /// 写入错误日志
        /// </summary>
        /// <param name="message">日志消息</param>
        public static void WriteError(string message)
        {
            WriteLog(message, LogLevel.Error);
        }
        
        /// <summary>
        /// 写入严重错误日志
        /// </summary>
        /// <param name="message">日志消息</param>
        public static void WriteFatal(string message)
        {
            WriteLog(message, LogLevel.Fatal);
        }
        
        /// <summary>
        /// 写入异常日志
        /// </summary>
        /// <param name="ex">异常对象</param>
        /// <param name="message">附加消息</param>
        public static void WriteException(Exception ex, string message = "")
        {
            if (ex == null) return;
            
            StringBuilder sb = new StringBuilder();
            if (!string.IsNullOrEmpty(message))
            {
                sb.AppendLine(message);
            }
            sb.AppendLine($"异常类型：{ex.GetType().Name}");
            sb.AppendLine($"异常消息：{ex.Message}");
            sb.AppendLine($"异常堆栈：{ex.StackTrace}");
            
            if (ex.InnerException != null)
            {
                sb.AppendLine("内部异常：");
                sb.AppendLine($"  类型：{ex.InnerException.GetType().Name}");
                sb.AppendLine($"  消息：{ex.InnerException.Message}");
            }
            
            WriteLog(sb.ToString(), LogLevel.Error);
        }
        
        /// <summary>
        /// 获取日志路径
        /// </summary>
        /// <returns></returns>
        private static string GetLogPath()
        {
            try
            {
                string configPath = ConfigurationManager.AppSettings["logPath"]?.ToString();
                if (!string.IsNullOrEmpty(configPath))
                {
                    return configPath;
                }
            }
            catch
            {
                // 配置读取失败时使用默认路径
            }
            
            // 默认日志路径
            return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
        }
        
        /// <summary>
        /// 获取日志级别字符串
        /// </summary>
        /// <param name="level">日志级别</param>
        /// <returns></returns>
        private static string GetLevelString(LogLevel level)
        {
            switch (level)
            {
                case LogLevel.Debug:
                    return "调试";
                case LogLevel.Info:
                    return "信息";
                case LogLevel.Warning:
                    return "警告";
                case LogLevel.Error:
                    return "错误";
                case LogLevel.Fatal:
                    return "严重";
                default:
                    return "未知";
            }
        }
        /// <summary>
        /// 删除过期日志
        /// </summary>
        public static void DeleteLog()
        {
            int deletedFileCount = 0;
            int deletedDirCount = 0;
            string logPath = GetLogPath();

            try
            {
                if (!Directory.Exists(logPath))
                {
                    Directory.CreateDirectory(logPath);
                    WriteLog("日志目录不存在，已创建：" + logPath, LogLevel.Info);
                    return;
                }

                // 获取日志保存天数配置，默认7天
                int logSaveTime = 7;
                try
                {
                    string configValue = ConfigurationManager.AppSettings["logSaveTime"]?.ToString();
                    if (!string.IsNullOrEmpty(configValue))
                    {
                        logSaveTime = Convert.ToInt32(configValue);
                    }
                }
                catch
                {
                    WriteLog("读取logSaveTime配置失败，使用默认值7天", LogLevel.Warning);
                }

                DateTime cutoffDate = DateTime.Now.AddDays(-logSaveTime);
                WriteLog($"开始清理{logSaveTime}天前的日志文件，截止日期：{cutoffDate:yyyy-MM-dd HH:mm:ss}", LogLevel.Info);

                // 递归清理日志目录
                CleanupLogDirectory(logPath, cutoffDate, ref deletedFileCount, ref deletedDirCount);

                if (deletedFileCount > 0 || deletedDirCount > 0)
                {
                    WriteLog($"日志清理完成，删除文件：{deletedFileCount}个，删除目录：{deletedDirCount}个", LogLevel.Info);
                }
                else
                {
                    WriteLog("日志清理完成，没有发现过期文件", LogLevel.Info);
                }
            }
            catch (Exception ex)
            {
                WriteLog($"清除过期日志文件失败：{ex.Message}", LogLevel.Error);
            }
        }

        /// <summary>
        /// 递归清理日志目录
        /// </summary>
        /// <param name="directoryPath">目录路径</param>
        /// <param name="cutoffDate">截止日期</param>
        /// <param name="deletedFileCount">删除文件计数</param>
        /// <param name="deletedDirCount">删除目录计数</param>
        private static void CleanupLogDirectory(string directoryPath, DateTime cutoffDate, ref int deletedFileCount, ref int deletedDirCount)
        {
            try
            {
                DirectoryInfo directory = new DirectoryInfo(directoryPath);
                
                // 清理文件
                foreach (FileInfo file in directory.GetFiles())
                {
                    try
                    {
                        // 检查文件创建时间和最后写入时间，取较新的一个
                        DateTime fileDate = file.CreationTime > file.LastWriteTime ? file.CreationTime : file.LastWriteTime;
                        
                        if (fileDate < cutoffDate)
                        {
                            // 只删除日志相关文件，避免误删其他文件
                            string extension = file.Extension.ToLower();
                            string fileName = file.Name.ToLower();
                            
                            if (extension == ".log" || extension == ".txt" || 
                                fileName.Contains("log") || fileName.Contains("error") || 
                                fileName.Contains("debug") || fileName.Contains("info"))
                            {
                                file.Delete();
                                deletedFileCount++;
                                WriteLog($"删除过期日志文件：{file.FullName}", LogLevel.Debug);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        WriteLog($"删除文件失败：{file.FullName}，错误：{ex.Message}", LogLevel.Warning);
                    }
                }

                // 递归处理子目录
                foreach (DirectoryInfo subDirectory in directory.GetDirectories())
                {
                    try
                    {
                        CleanupLogDirectory(subDirectory.FullName, cutoffDate, ref deletedFileCount, ref deletedDirCount);
                        
                        // 如果子目录为空且创建时间早于截止日期，则删除该目录
                        if (subDirectory.GetFiles().Length == 0 && 
                            subDirectory.GetDirectories().Length == 0 && 
                            subDirectory.CreationTime < cutoffDate)
                        {
                            subDirectory.Delete();
                            deletedDirCount++;
                            WriteLog($"删除空的过期日志目录：{subDirectory.FullName}", LogLevel.Debug);
                        }
                    }
                    catch (Exception ex)
                    {
                        WriteLog($"处理子目录失败：{subDirectory.FullName}，错误：{ex.Message}", LogLevel.Warning);
                    }
                }
            }
            catch (Exception ex)
            {
                WriteLog($"清理目录失败：{directoryPath}，错误：{ex.Message}", LogLevel.Error);
            }
        }
    }
}
